/**
 * @file port_ble_msg.c
 * @brief 
 * @author dotc (dotchan@qq.com)
 * @date 2025-01-21
 * 
 * @copyright Copyright (c) 2025 by 深圳市鹏天微智能科技有限公司, All Rights Reserved.
 */

#if defined(CONFIG_PORT_BLE_ENABLE)

/* ==================== [Includes] ========================================== */

// 单独控制本文件功能的优先级
#define XF_LOG_LEVEL            CONFIG_PORT_BASE_LOG_LEVEL

#include "xf_ble_gap.h"
#include "xf_utils.h"
#include "xf_init.h"
#include "xf_sys.h"

#include "port_ble_msg.h"
#include "port_ble_internal.h"
#include "bledef.h"

#include "drvs.h"

/* ==================== [Defines] =========================================== */

#define TAG "port_base"

/* ==================== [Typedefs] ========================================== */

typedef struct _port_msg_tbl_lookup_info_t
{
    uint8_t index;  // 消息对应在消息表 (msg_tbl) 中的索引值 (非消息组的起始索引，是加上消息本身的实际位置的索引)
    uint8_t bit_n;  // 消息在消息表数组成员中的标志位
} port_msg_tbl_lookup_info_t;

/* ==================== [Static Prototypes] ================================= */

static msg_info_list_index_t port_msg_info_list_get_free_index(void);
static int _all_msg_handler(
    msg_id_t msgid, const void *param, 
    task_id_t dest_id, task_id_t src_id);
static inline void _port_msg_grp_tbl_info_get(
    port_msg_grp_type_t grp_type,
    msg_index_t msg_index,
    port_msg_tbl_lookup_info_t *lookup_info
);

static port_msg_early_handler_status_t port_msg_early_handler_ble_evt(
    uint8_t conn_id,
    port_msg_grp_type_t grp_type,
    msg_index_t msg_index,
    const void *param
);

/* ==================== [Global Variables] ================================== */

uint32_t port_sys_clk = SYS_GET_CLOCK();

/* ==================== [Static Variables] ================================== */

static port_msg_tbl_t s_msg_tbl = {};

static port_msg_info_t *(s_list_msg_info[MSG_INFO_LIST_MAX_CNT]) = {NULL};

static uint8_t s_list_msg_info_index_current = 0;

static const msg_param_size_t s_map_port_msg_index_to_param_size_gatt[MSG_INDEX_MAX_GATT] =
{
    [MSG_IDX(GATT_CMP_EVT)]                 = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gatt_cmp_evt)),
    // [MSG_IDX(GATT_CLIENT_CMD)] = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gatt_client_cmd)),
    [MSG_IDX(GATT_EXC_MTU_CMD)]             = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gatt_exc_mtu_cmd)),
    [MSG_IDX(GATT_DISC_CMD)]                = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gatt_disc_cmd)),
    [MSG_IDX(GATT_READ_CMD)]                = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gatt_read_cmd)),
    [MSG_IDX(GATT_WRITE_CMD)]               = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gatt_write_cmd)),
    [MSG_IDX(GATT_EXECUTE_WRITE_CMD)]       = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gatt_execute_write_cmd)),
    [MSG_IDX(GATT_MTU_CHANGED_IND)]         = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gatt_mtu_changed_ind)),
    [MSG_IDX(GATT_DISC_SVC_IND)]            = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gatt_disc_svc_ind)),
    [MSG_IDX(GATT_DISC_SVC_INCL_IND)]       = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gatt_disc_svc_incl_ind)),
    [MSG_IDX(GATT_DISC_CHAR_IND)]           = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gatt_disc_char_ind)),
    [MSG_IDX(GATT_DISC_CHAR_DESC_IND)]      = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gatt_disc_char_desc_ind)),
    [MSG_IDX(GATT_READ_IND)]                = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gatt_read_ind)),
    [MSG_IDX(GATT_EVENT_IND)]               = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gatt_event_ind)),
    [MSG_IDX(GATT_EVENT_REQ_IND)]           = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gatt_event_req_ind)),
    [MSG_IDX(GATT_EVENT_CFM)]               = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gatt_event_cfm)),
    [MSG_IDX(GATT_REG_TO_PEER_EVT_CMD)]     = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gatt_reg_to_peer_evt_cmd)),
    [MSG_IDX(GATT_SEND_EVT_CMD)]            = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gatt_send_evt_cmd)),
    // [MSG_IDX(GATT_SERVER_CFM)] = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gatt_server_cfm)),
    [MSG_IDX(GATT_READ_CFM)]                = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gatt_read_cfm)),
    [MSG_IDX(GATT_WRITE_CFM)]               = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gatt_write_cfm)),
    [MSG_IDX(GATT_ATT_INFO_CFM)]            = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gatt_att_info_cfm)),
    [MSG_IDX(GATT_READ_REQ_IND)]            = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gatt_read_req_ind)),
    [MSG_IDX(GATT_WRITE_REQ_IND)]           = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gatt_write_req_ind)),
    [MSG_IDX(GATT_ATT_INFO_REQ_IND)]        = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gatt_att_info_req_ind)),
    [MSG_IDX(GATT_SDP_SVC_DISC_CMD)]        = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gatt_sdp_svc_disc_cmd)),
    [MSG_IDX(GATT_SDP_SVC_IND)]             = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gatt_sdp_svc_ind)),
    // [MSG_IDX(GATT_TRANSACTION_TO_ERROR_IND)] = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gatt_transaction_to_error_ind)),
    [MSG_IDX(GATT_UNKNOWN_MSG_IND)]         = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gatt_unknown_msg_ind)),
    [MSG_IDX(GATT_READ_DB_HASH_CMD)]        = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gatt_read_db_hash_cmd)),
    [MSG_IDX(GATT_DB_HASH_IND)]             = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gatt_db_hash_ind)),
    [MSG_IDX(GATT_ROBUST_DB_CACHE_EN_CMD)]  = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gatt_robust_db_cache_en_cmd)),
    // [MSG_IDX(GATT_DB_CACHE_OUT_OF_SYNC_IND)] = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gatt_db_cache_out_of_sync_ind)),
    [MSG_IDX(GATT_SVC_CHG_REQ_IND)]         = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gatt_svc_chg_req_ind)),
    // [MSG_IDX(GATT_SVC_CHG_CFM)]          = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gatt_svc_chg_cfm)),
    [MSG_IDX(GATT_CON_INFO_IND)]            = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gatt_con_info_ind)),
};

static const msg_param_size_t s_map_port_msg_index_to_param_size_gapm[MSG_INDEX_MAX_GAPM] =
{
    [MSG_IDX(GAPM_CMP_EVT)] = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_cmp_evt)),

    // [MSG_IDX(GAPM_CONFIG_CMD)] = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_config_cmd)),
    [MSG_IDX(GAPM_RESET_CMD)]               = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_reset_cmd)),
    // [MSG_IDX(GAPM_SET_DEV_CONFIG_CMD)] = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_set_dev_config_cmd)),
    [MSG_IDX(GAPM_SET_CHANNEL_MAP_CMD)]     = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_set_channel_map_cmd)),
    [MSG_IDX(GAPM_GET_DEV_INFO_CMD)]        = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_get_dev_info_cmd)),
    [MSG_IDX(GAPM_DEV_VERSION_IND)]         = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_dev_version_ind)),
    [MSG_IDX(GAPM_DEV_BDADDR_IND)]          = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_dev_bdaddr_ind)),
    [MSG_IDX(GAPM_DEV_ADV_TX_POWER_IND)]    = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_dev_adv_tx_power_ind)),
    [MSG_IDX(GAPM_PEER_NAME_IND)]           = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_peer_name_ind)),
    // [MSG_IDX(GAPM_SEC_ENC_AES_CMD)] = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_sec_enc_aes_cmd)),
    [MSG_IDX(GAPM_RESOLV_ADDR_CMD)]         = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_resolv_addr_cmd)),
    [MSG_IDX(GAPM_GEN_RAND_ADDR_CMD)]       = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_gen_rand_addr_cmd)),
    [MSG_IDX(GAPM_USE_ENC_BLOCK_CMD)]       = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_use_enc_block_cmd)),
    [MSG_IDX(GAPM_GEN_RAND_NB_CMD)]         = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_gen_rand_nb_cmd)),
    [MSG_IDX(GAPM_ADDR_SOLVED_IND)]         = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_addr_solved_ind)),
    [MSG_IDX(GAPM_USE_ENC_BLOCK_IND)]       = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_use_enc_block_ind)),
    [MSG_IDX(GAPM_GEN_RAND_NB_IND)]         = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_gen_rand_nb_ind)),
    [MSG_IDX(GAPM_PROFILE_TASK_ADD_CMD)]    = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_profile_task_add_cmd)),
    [MSG_IDX(GAPM_PROFILE_ADDED_IND)]       = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_profile_added_ind)),
    [MSG_IDX(GAPM_UNKNOWN_TASK_IND)]        = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_unknown_task_ind)),
    [MSG_IDX(GAPM_SUGG_DFLT_DATA_LEN_IND)]  = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_sugg_dflt_data_len_ind)),
    [MSG_IDX(GAPM_MAX_DATA_LEN_IND)]        = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_max_data_len_ind)),
    [MSG_IDX(GAPM_RAL_ADDR_IND)]            = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_ral_addr_ind)),
    [MSG_IDX(GAPM_SET_IRK_CMD)]             = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_set_irk_cmd)),
    [MSG_IDX(GAPM_LEPSM_REGISTER_CMD)]      = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_lepsm_register_cmd)),
    [MSG_IDX(GAPM_LEPSM_UNREGISTER_CMD)]    = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_lepsm_unregister_cmd)),
    [MSG_IDX(GAPM_LE_TEST_MODE_CTRL_CMD)]   = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_le_test_mode_ctrl_cmd)),
    [MSG_IDX(GAPM_LE_TEST_END_IND)]         = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_le_test_end_ind)),
    [MSG_IDX(GAPM_ISO_STAT_IND)]            = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_iso_stat_ind)),
    // [MSG_IDX(GAPM_SEC_ENC_ECC_CMD)] = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_sec_enc_ecc_cmd)),
    [MSG_IDX(GAPM_GEN_DH_KEY_CMD)]          = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_gen_dh_key_cmd)),
    [MSG_IDX(GAPM_GET_PUB_KEY_CMD)]         = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_get_pub_key_cmd)),
    [MSG_IDX(GAPM_GEN_DH_KEY_IND)]          = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_gen_dh_key_ind)),
    [MSG_IDX(GAPM_PUB_KEY_IND)]             = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_pub_key_ind)),
    [MSG_IDX(GAPM_GET_RAL_ADDR_CMD)]        = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_get_ral_addr_cmd)),
    [MSG_IDX(GAPM_LIST_SET_CMD)]            = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_list_set_cmd)),
    [MSG_IDX(GAPM_LIST_SIZE_IND)]           = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_list_size_ind)),
    // [MSG_IDX(GAPM_ACTIVITY_CMP_EVT)] = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_activity_cmp_evt)),
    // [MSG_IDX(GAPM_ACTIVITY_CMD)] = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_activity_cmd)),
    [MSG_IDX(GAPM_ACTIVITY_CREATE_CMD)]     = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_activity_create_cmd)),
    [MSG_IDX(GAPM_ACTIVITY_START_CMD)]      = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_activity_start_cmd)),
    [MSG_IDX(GAPM_ACTIVITY_STOP_CMD)]       = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_activity_stop_cmd)),
    [MSG_IDX(GAPM_ACTIVITY_DELETE_CMD)]     = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_activity_delete_cmd)),
    [MSG_IDX(GAPM_ACTIVITY_CREATED_IND)]    = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_activity_created_ind)),

    [MSG_IDX(GAPM_ACTIVITY_STOPPED_IND)]    = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_activity_stopped_ind)),

    [MSG_IDX(GAPM_SET_ADV_DATA_CMD)]        = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_set_adv_data_cmd)),
    [MSG_IDX(GAPM_EXT_ADV_REPORT_IND)]      = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_ext_adv_report_ind)),
    [MSG_IDX(GAPM_SCAN_REQUEST_IND)]        = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_scan_request_ind)),
    [MSG_IDX(GAPM_SYNC_ESTABLISHED_IND)]    = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_sync_established_ind)),
    [MSG_IDX(GAPM_MAX_ADV_DATA_LEN_IND)]    = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_max_adv_data_len_ind)),
    [MSG_IDX(GAPM_NB_ADV_SETS_IND)]         = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_nb_adv_sets_ind)),
    [MSG_IDX(GAPM_DEV_TX_PWR_IND)]          = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_dev_tx_pwr_ind)),
    [MSG_IDX(GAPM_DEV_RF_PATH_COMP_IND)]    = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapm_dev_rf_path_comp_ind)),
};

static const msg_param_size_t s_map_port_msg_index_to_param_size_gapc[MSG_INDEX_MAX_GAPC] =
{
    [MSG_IDX(GAPC_CMP_EVT)]                 = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_cmp_evt)),
    [MSG_IDX(GAPC_CONNECTION_REQ_IND)]      = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_connection_req_ind)),
    [MSG_IDX(GAPC_CONNECTION_IND)]          = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_connection_ind)),
    [MSG_IDX(GAPC_DISCONNECT_IND)]          = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_disconnect_ind)),
    [MSG_IDX(GAPC_DISCONNECT_CMD)]          = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_disconnect_cmd)),
    [MSG_IDX(GAPC_CONNECTION_CFG)]          = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_connection_cfg)),
    [MSG_IDX(GAPC_GET_INFO_CMD)]            = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_get_info_cmd)),
    [MSG_IDX(GAPC_PEER_ATT_INFO_IND)]       = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_peer_att_info_ind)),
    [MSG_IDX(GAPC_PEER_VERSION_IND)]        = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_peer_version_ind)),
    [MSG_IDX(GAPC_PEER_FEATURES_IND)]       = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_peer_features_ind)),
    [MSG_IDX(GAPC_CON_RSSI_IND)]            = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_con_rssi_ind)),
    [MSG_IDX(GAPC_GET_DEV_INFO_REQ_IND)]    = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_get_dev_info_req_ind)),
    [MSG_IDX(GAPC_GET_DEV_INFO_CFM)]        = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_get_dev_info_cfm)),
    [MSG_IDX(GAPC_SET_DEV_INFO_REQ_IND)]    = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_set_dev_info_req_ind)),
    [MSG_IDX(GAPC_SET_DEV_INFO_CFM)]        = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_set_dev_info_cfm)),
    [MSG_IDX(GAPC_PARAM_UPDATE_CMD)]        = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_param_update_cmd)),
    [MSG_IDX(GAPC_PARAM_UPDATE_REQ_IND)]    = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_param_update_req_ind)),
    [MSG_IDX(GAPC_PARAM_UPDATE_CFM)]        = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_param_update_cfm)),
    [MSG_IDX(GAPC_PARAM_UPDATED_IND)]       = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_param_updated_ind)),
    // [MSG_IDX(GAPC_SMP_CMD)] = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_smp_cmd)),
    [MSG_IDX(GAPC_BOND_CMD)]                = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_bond_cmd)),
    [MSG_IDX(GAPC_ENCRYPT_CMD)]             = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_encrypt_cmd)),
    [MSG_IDX(GAPC_SECURITY_CMD)]            = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_security_cmd)),
    [MSG_IDX(GAPC_SIGN_CMD)]                = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_sign_cmd)),
    [MSG_IDX(GAPC_BOND_REQ_IND)]            = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_bond_req_ind)),
    [MSG_IDX(GAPC_BOND_CFM)]                = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_bond_cfm)),
    [MSG_IDX(GAPC_BOND_IND)]                = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_bond_ind)),
    [MSG_IDX(GAPC_ENCRYPT_REQ_IND)]         = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_encrypt_req_ind)),
    [MSG_IDX(GAPC_ENCRYPT_CFM)]             = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_encrypt_cfm)),
    [MSG_IDX(GAPC_ENCRYPT_IND)]             = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_encrypt_ind)),
    [MSG_IDX(GAPC_SECURITY_IND)]            = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_security_ind)),
    [MSG_IDX(GAPC_SIGN_COUNTER_IND)]        = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_sign_counter_ind)),
    [MSG_IDX(GAPC_CON_CHANNEL_MAP_IND)]     = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_con_channel_map_ind)),
    [MSG_IDX(GAPC_SET_LE_PING_TO_CMD)]      = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_set_le_ping_to_cmd)),
    [MSG_IDX(GAPC_LE_PING_TO_VAL_IND)]      = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_le_ping_to_val_ind)),
    // [MSG_IDX(GAPC_LE_PING_TO_IND)] = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_le_ping_to_ind)),
    [MSG_IDX(GAPC_SET_LE_PKT_SIZE_CMD)]     = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_set_le_pkt_size_cmd)),
    [MSG_IDX(GAPC_LE_PKT_SIZE_IND)]         = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_le_pkt_size_ind)),
    [MSG_IDX(GAPC_KEY_PRESS_NOTIFICATION_CMD)] = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_key_press_notif_cmd)),
    [MSG_IDX(GAPC_KEY_PRESS_NOTIFICATION_IND)] = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_key_press_notif_ind)),
    [MSG_IDX(GAPC_SET_PHY_CMD)]             = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_set_phy_cmd)),
    [MSG_IDX(GAPC_LE_PHY_IND)]              = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_le_phy_ind)),
    [MSG_IDX(GAPC_CHAN_SEL_ALGO_IND)]       = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_chan_sel_algo_ind)),
    [MSG_IDX(GAPC_SET_PREF_SLAVE_LATENCY_CMD)] = sizeof(GET_MSG_PARAM_TYPE_BY_NAME(gapc_set_pref_slave_latency_cmd)),
};

/**
 * @brief 消息组类型 与 消息参数大小映射表的 映射
 * @note sdk 侧事件分发中设置消息 (msg) 时使用
 */
static const uint8_t *(s_map_port_msg_grp_to_param_size_map[_PORT_MSG_GRP_TYPE_MAX]) =
{
    [PORT_MSG_GRP_TYPE_GATT] = s_map_port_msg_index_to_param_size_gatt,
    [PORT_MSG_GRP_TYPE_GAPM] = s_map_port_msg_index_to_param_size_gapm,
    [PORT_MSG_GRP_TYPE_GAPC] = s_map_port_msg_index_to_param_size_gapc,
};

/**
 * @brief 消息组类型 (msg_grp_type) 与 消息表 (msg_tbl) (起始) 索引值的映射 
 * @note sdk 侧事件分发中设置消息 (msg) 时使用
 */
static const port_msg_grp_tbl_index_t s_map_port_msg_grp_to_tbl_index[_PORT_MSG_GRP_TYPE_MAX] =
{
    [PORT_MSG_GRP_TYPE_LLC]     = PORT_MSG_GRP_TBL_INDEX_LLC,
    [PORT_MSG_GRP_TYPE_LLD]     = PORT_MSG_GRP_TBL_INDEX_LLD,
    [PORT_MSG_GRP_TYPE_HCI]     = PORT_MSG_GRP_TBL_INDEX_HCI,
    [PORT_MSG_GRP_TYPE_L2CC]    = PORT_MSG_GRP_TBL_INDEX_L2CC,
    [PORT_MSG_GRP_TYPE_GATT]    = PORT_MSG_GRP_TBL_INDEX_GATT,
    [PORT_MSG_GRP_TYPE_GAPM]    = PORT_MSG_GRP_TBL_INDEX_GAPM,
    [PORT_MSG_GRP_TYPE_GAPC]    = PORT_MSG_GRP_TBL_INDEX_GAPC,
    [PORT_MSG_GRP_TYPE_APP]     = PORT_MSG_GRP_TBL_INDEX_APP,
    [PORT_MSG_GRP_TYPE_MESH]     = PORT_MSG_GRP_TBL_INDEX_MESH,
};

static port_msg_early_handler_info_t s_map_msg_to_early_handler_gapm[] =
{
    {MSG_IDX(GAPM_EXT_ADV_REPORT_IND), port_msg_early_handler_gap_scan_result},
    {0,0}
    // {, port_msg_early_handler_gap_pair_end},
};

static port_msg_early_handler_info_t s_map_msg_to_early_handler_gapc[] = 
{
    {MSG_IDX(GAPC_CONNECTION_REQ_IND), port_msg_early_handler_gap_connect_req},
    {MSG_IDX(GAPC_CONNECTION_IND), port_msg_early_handler_gap_connect},
    {MSG_IDX(GAPC_BOND_REQ_IND), port_msg_early_handler_gap_pair_req},
    {MSG_IDX(GAPC_BOND_IND), port_msg_early_handler_gap_pair_result},
    {MSG_IDX(GAPC_DISCONNECT_IND), port_msg_early_handler_gap_disconnect},
    {MSG_IDX(GAPC_PARAM_UPDATE_REQ_IND), port_msg_early_handler_gap_conn_params_update_req},
    {MSG_IDX(GAPC_PARAM_UPDATED_IND), port_msg_early_handler_gap_conn_params_update_ind},
    {MSG_IDX(GAPC_CMP_EVT), port_msg_early_handler_gap_cmplt_evt},
    {0,0}
};

static port_msg_early_handler_info_t s_map_msg_to_early_handler_gatt[] =
{
    {MSG_IDX(GATT_CMP_EVT), port_msg_early_handler_gatt_cmplt_evt},
    {MSG_IDX(GATT_READ_IND), port_msg_early_handler_gatt_client_read_rsp},
    {0,0}
    // {, port_msg_early_handler_gap_pair_end},
};

static port_msg_early_handler_info_t *(s_map_msg_to_early_handler[_PORT_MSG_GRP_TYPE_MAX]) =
{
    [PORT_MSG_GRP_TYPE_GAPM] = s_map_msg_to_early_handler_gapm,
    [PORT_MSG_GRP_TYPE_GAPC] = s_map_msg_to_early_handler_gapc,
    [PORT_MSG_GRP_TYPE_GATT] = s_map_msg_to_early_handler_gatt,
};

/* ==================== [Macros] ============================================ */

/* ==================== [Global Functions] ================================== */

port_msg_info_t **port_msg_info_list_get(void)
{
    return s_list_msg_info;
}

xf_err_t port_msg_tbl_set(
    port_msg_grp_type_t grp_type,
    msg_index_t msg_index,
    const void *param
)
{
    port_msg_tbl_lookup_info_t lookup_info = {0};
    _port_msg_grp_tbl_info_get(grp_type, msg_index, &lookup_info);
    
    XF_LOGD(TAG, ">> msg grp:%d,index:%#X;tbl_index:%d,bit_n:%d",
        grp_type, msg_index, msg_index, lookup_info.index, lookup_info.bit_n);

    BIT_SET1(s_msg_tbl.array_u8[lookup_info.index], lookup_info.bit_n);

    msg_info_list_index_t list_index = port_msg_info_list_get_free_index();
    // XF_CHECK(list_index == MSG_INFO_LIST_INDEX_INVALID, XF_ERR_BUSY, 
    //     TAG, "s_list_msg_info all are not free");

    msg_param_size_t param_size = 
        s_map_port_msg_grp_to_param_size_map[grp_type][msg_index];

    // XF_LOGD(TAG, "list_index:%d,param_size:%d", list_index, param_size);

    s_list_msg_info[list_index] = xf_malloc(sizeof(port_msg_info_t) + param_size);
    XF_CHECK(s_list_msg_info[list_index] == NULL, XF_ERR_NO_MEM, 
        TAG, "s_list_msg_info[%d] malloc failed!", list_index);

    s_list_msg_info[list_index]->grp_type = grp_type;
    s_list_msg_info[list_index]->msg_index = msg_index;

    if(param_size == 0)
    {
        XF_LOGW(TAG,"msg[%d][%d] param size == 0", grp_type, msg_index);
        return XF_OK;
    }

    xf_memcpy(s_list_msg_info[list_index]->param, param, param_size);
    return XF_OK;
}

xf_err_t port_msg_tbl_clear_by_index(
    msg_info_list_index_t list_index
)
{
    XF_ASSERT(list_index < MSG_INFO_LIST_MAX_CNT, XF_ERR_INVALID_ARG,
        TAG, "list_index out of range (%d)", MSG_INFO_LIST_MAX_CNT);
    
    if(s_list_msg_info[list_index] == NULL)
    {
        return XF_OK;
    }

    port_msg_tbl_lookup_info_t lookup_info = {0};
    _port_msg_grp_tbl_info_get(s_list_msg_info[list_index]->grp_type,
        s_list_msg_info[list_index]->msg_index, &lookup_info);

    /* FIXME 因为 SDK 侧某些事件不是唯一的 (有可能是多个不同的触发源，如 XXX_CMP )
        所以此处暂时不做清除标志位处理。
        此处理会让查询事件时，一些前面触发过的事件检查在查找表中会检查到触发，
        不过下面仍会在事件信息缓存链中再一步匹配。
    */
    // BIT_SET0(s_msg_tbl.array_u8[lookup_info.index], lookup_info.bit_n);

    xf_free(s_list_msg_info[list_index]);
    s_list_msg_info[list_index] = NULL;
    return XF_OK;
}

msg_info_list_index_t port_msg_tbl_get(
    port_msg_grp_type_t grp_type,
    msg_index_t msg_index,
    port_msg_param_var_t **param_get,
    port_msg_param_match_info_t param_match,
    uint16_t timeout_ms
)
{
    xf_ms_t ms_end = xf_sys_time_get_ms() + timeout_ms; 

    bool bit_flag;
    port_msg_tbl_lookup_info_t lookup_info = {0};

    _port_msg_grp_tbl_info_get(grp_type, msg_index, &lookup_info);

    while (1)
    {
        ble_schedule();
        /* 检查目标事件是否触发 */
        bit_flag = BIT_GET(s_msg_tbl.array_u8[lookup_info.index], lookup_info.bit_n);
    
        if(bit_flag == true)
        {
            uint8_t i = 0;
            /* 检查消息的信息列表是否有匹配的 消息类型及消息索引 */
            for(;i < MSG_INFO_LIST_MAX_CNT; i++)
            {
                if(s_list_msg_info[i] == NULL)
                {
                    continue;
                }    
                if( (s_list_msg_info[i]->grp_type == grp_type)
                &&  (s_list_msg_info[i]->msg_index == msg_index) )
                {
                    /* 参数匹配信息中比较的大小不为 0 -> 还需匹配参数中某项值 */
                    if (param_match.size_byte != 0)
                    {
                        uint8_t *array_u8 = (uint8_t *)s_list_msg_info[i]->param;
                        XF_LOGD(TAG, "match val:%d,pos:%d,size:%d,param_val:%d", 
                            param_match.val, param_match.pos_index, param_match.size_byte, 
                            ((uint8_t *)s_list_msg_info[i]->param)[param_match.pos_index]);
                        if(xf_memcmp(&array_u8[param_match.pos_index], &param_match.val, param_match.size_byte) != 0)
                        {
                            continue;
                        }
                        XF_LOGD(TAG, "match ok val:%d", param_match.val);
                    }
                    /* 不关注参数内容 -> 直接返回事件触发情况 */
                    if(param_get == NULL)
                    {
                        return i;
                    }
                    *param_get = (port_msg_param_var_t *)s_list_msg_info[i]->param;
                    return i;
                }
            }
        }
        if(ms_end < xf_sys_time_get_ms())
        {
            return MSG_INFO_LIST_INDEX_INVALID;
        }
    }
}

/**
 ****************************************************************************************
 * @brief Dispatch TASK_APP message to sub-handler.
 *
 * @param[in] msgid     Id of the message received.
 * @param[in] task_idx  Index of the receiving task instance.
 *
 * @return Handler of the message or NULL.
 ****************************************************************************************
 */
__TASKFN void* app_task_dispatch(msg_id_t msg_id, uint8_t task_idx)
{
    type_id_t type_id = (type_id_t) MSG_TYPE(msg_id);
    if( type_id < _TID_BASE || _TID_MAX <= type_id)
    {
        XF_LOGW(TAG, "Invalid msg type_id!");
        return NULL;
    }
    
    // return s_map_msg_grp_handler[type_id];
    return _all_msg_handler;
}

static int _all_msg_handler(
    msg_id_t msg_id, const void *param, 
    task_id_t dest_id, task_id_t src_id)
{
    uint8_t port_msg_grp_type = PORT_MSG_GRP_GET_FROM_TID(MSG_TYPE(msg_id));
    uint8_t msg_index = MSG_IDX(msg_id);
    port_msg_early_handler_status_t early_handler_status 
        = port_msg_early_handler_ble_evt(TASK_IDX(src_id), port_msg_grp_type, msg_index, param);
    
    if(early_handler_status != PORT_MSG_EARLY_HANDLER_STATUS_NONE)
    {
        XF_LOGD(TAG, "<< eraly:msg grp:%d,index:%#02X,conn_id:%d", 
            port_msg_grp_type, msg_index, TASK_IDX(src_id));
        if(early_handler_status == PORT_MSG_EARLY_HANDLER_STATUS_CMPLT)
        {
            return MSG_STATUS_FREE;
        }
    }

    xf_err_t ret = port_msg_tbl_set(
        port_msg_grp_type, msg_index, param);
    XF_ASSERT(ret == XF_OK, MSG_STATUS_FREE,
        TAG, "port_msg_tbl_set error:%d", ret);

    return MSG_STATUS_FREE;
}

static port_msg_early_handler_status_t port_msg_early_handler_ble_evt(
    uint8_t conn_id,
    port_msg_grp_type_t grp_type,
    msg_index_t msg_index,
    const void *param
)
{
    port_msg_early_handler_info_t *map_handler_info = s_map_msg_to_early_handler[grp_type];
    if(map_handler_info == NULL)
    {
        return PORT_MSG_EARLY_HANDLER_STATUS_NONE;
    }

    uint8_t i = 0;
    while (1)
    {
        if(map_handler_info[i].handler == NULL)
        {
            return PORT_MSG_EARLY_HANDLER_STATUS_NONE;
        }
        if(msg_index == map_handler_info[i].msg_index)
        {
            return map_handler_info[i].handler(conn_id, param);
        }
        ++i;
    }
}

static msg_info_list_index_t port_msg_info_list_get_free_index(void)
{
    msg_info_list_index_t index = s_list_msg_info_index_current++;
    if(s_list_msg_info_index_current >= MSG_INFO_LIST_MAX_CNT)
    {
        s_list_msg_info_index_current = 0;
    }

    port_msg_tbl_clear_by_index(index);
    return index;
    // uint8_t i = 0;
    // for(;i < MSG_INFO_LIST_MAX_CNT; i++)
    // {
    //     if(s_list_msg_info[i] == NULL)
    //     {
    //         return i;
    //     }    
    // }
    // return MSG_INFO_LIST_INDEX_INVALID;
}

static inline void _port_msg_grp_tbl_info_get(
    port_msg_grp_type_t grp_type,
    msg_index_t msg_index,
    port_msg_tbl_lookup_info_t *lookup_info
)
{
    lookup_info->index = 
        s_map_port_msg_grp_to_tbl_index[grp_type] + msg_index/PORT_MSG_TBL_ITEM_BIT_CNT;
    lookup_info->bit_n = msg_index%PORT_MSG_TBL_ITEM_BIT_CNT;
}

msg_info_list_index_t port_msg_evt_get(
    uint32_t msg_evt,
    port_msg_param_var_t **param_get,
    uint16_t timeout_ms)
{
    port_msg_evt_info_t *evt_info = (port_msg_evt_info_t *)&msg_evt;

    return port_msg_tbl_get(
        evt_info->grp_type,
        evt_info->msg_index,
        param_get,
        evt_info->param_match,
        timeout_ms
    );
}
#endif
